package com.nosql.db.core.wal;

import com.nosql.db.core.modul.Document;
import com.nosql.db.core.storage.LSMStore;
import com.nosql.db.core.storage.MemTable;


import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
public class WAL {
    private final Path walFile;
    private RandomAccessFile raf;
    private boolean inBatch = false;
    private BufferedWriter writer;
    private LSMStore storage;

    public synchronized void beginBatch() {
        inBatch = true;
    }

    public synchronized void endBatch() throws IOException {
        inBatch = false;
        writer.flush(); // 仅需flush writer
        FileChannel channel = FileChannel.open(walFile, StandardOpenOption.WRITE);
        channel.force(true); // 确保物理写入
        channel.close();
    }

    public WAL(Path filePath) throws IOException {
        this.walFile = filePath;

        if (!Files.exists(filePath)) {
            Files.createFile(filePath);
        }

        // 使用BufferedWriter替换RandomAccessFile
        this.writer = Files.newBufferedWriter(filePath,
                StandardCharsets.UTF_8,
                StandardOpenOption.CREATE,
                StandardOpenOption.APPEND);
    }

    public synchronized void writeEntry(WALEntry entry) throws IOException {
        String line = entry.toTxtFormat(); // 新增文本格式化方法
        writer.write(line);
        writer.newLine();

        if (!inBatch) {
            writer.flush(); // 非批量模式立即刷盘
        }
    }

    public void replay(MemTable memTable) throws IOException {
        try (BufferedReader reader = Files.newBufferedReader(walFile)) {
            String line;
            while ((line = reader.readLine()) != null) {
                WALEntry entry = WALEntry.parseFromTxt(line); // 新增文本解析方法
                applyEntry(entry, memTable);
            }
        }
    }


    private void applyEntry(WALEntry entry, MemTable memTable) {
        switch (entry.getOperation()) {
            case PUT, UPDATE:
                Document doc = entry.getDocument();
                Document existingDoc = memTable.get(doc.getId());
                if (existingDoc != null) {
                    existingDoc.mergeData(doc.getData());
                    memTable.put(existingDoc);
                } else {
                    memTable.put(doc);
                }
                break;
            case CREATE_COLLECTION:
                storage.createCollection(entry.getCollection());
                    break;
            case DELETE:
                memTable.delete(entry.getDocumentId());
                break;
        }
    }

    public void clear() throws IOException {
        Files.write(walFile, new byte[0], StandardOpenOption.TRUNCATE_EXISTING);
    }

    public void close() throws IOException {
        raf.close();
    }
    public void rotate() throws IOException {
        Path rotated = walFile.resolveSibling(walFile.getFileName() + ".rotated");
        Files.move(walFile, rotated);
        this.writer = Files.newBufferedWriter(walFile, StandardCharsets.UTF_8, StandardOpenOption.CREATE);
    }
    // 在WAL.java中添加以下方法
    public Path getWalFile() {
        return this.walFile; // 假设WAL类已有walFile字段存储路径
    }

}